/*
 * SessionPanel.java
 *
 * Created on 28 juin 2010, 21:14:01
 */

package darknet.application.chat.gui;

import darknet.application.chat.spec.Session;
import darknet.application.chat.spec.SessionObserver;
import darknet.application.chat.impl.net.message.PrivateMessage;
import darknet.application.chat.impl.net.message.SessionExitMessage;

import java.io.IOException;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingWorker;

/**
 * A panel for private message exchance.
 *
 * @author Yoyo
 */
public class SessionPanel extends JPanel implements SessionObserver {

    /** Serial version */
    private static final long serialVersionUID = 1L;

    /** The session */
    private Session session = null;

    /** Chat application panel */
    private ChatApplicationPanel master = null;

    /** Determine if the session if closed, or not. */
    private boolean isClosed = false;

    /** 
     * Creates new form SessionPanel
     * @param session
     */
    public SessionPanel(Session session, ChatApplicationPanel master) {

        if (session == null) {
            throw new IllegalArgumentException("session is null");
        }
        this.session = session;

        if (master == null) {
            throw new IllegalArgumentException("master is invalid (null)");
        }
        this.master = master;

        initComponents();

        labelNickname.setText(session.getNode().getName());
    }

    /**
     * Get the node name of the distant node.
     * @return
     */
    public String getNodeName() {
        return session.getNode().getName();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        editorpaneMessage = new javax.swing.JEditorPane();
        btnSend = new javax.swing.JButton();
        jLabel1 = new javax.swing.JLabel();
        labelNickname = new javax.swing.JLabel();
        jScrollPane2 = new javax.swing.JScrollPane();
        messages = new javax.swing.JTextPane();
        btnClose = new javax.swing.JButton();

        jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);

        editorpaneMessage.setToolTipText("Enter your message here.");
        editorpaneMessage.setCursor(new java.awt.Cursor(java.awt.Cursor.TEXT_CURSOR));
        editorpaneMessage.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyTyped(java.awt.event.KeyEvent evt) {
                editorpaneMessageKeyTyped(evt);
            }
        });
        jScrollPane1.setViewportView(editorpaneMessage);

        btnSend.setText("Send");
        btnSend.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnSendActionPerformed(evt);
            }
        });

        jLabel1.setText("Private Chat Session with :");

        labelNickname.setText("[nickname]");

        jScrollPane2.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);

        messages.setEditable(false);
        jScrollPane2.setViewportView(messages);

        btnClose.setText("close");
        btnClose.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnCloseActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 732, Short.MAX_VALUE)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addComponent(jScrollPane1)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(btnSend, javax.swing.GroupLayout.PREFERRED_SIZE, 87, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jLabel1)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(labelNickname, javax.swing.GroupLayout.DEFAULT_SIZE, 497, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(btnClose)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel1)
                    .addComponent(labelNickname)
                    .addComponent(btnClose))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 275, Short.MAX_VALUE)
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                    .addComponent(btnSend, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 80, Short.MAX_VALUE))
                .addContainerGap())
        );
    }// </editor-fold>//GEN-END:initComponents

    private void btnSendActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSendActionPerformed

        sendTypedMessage();
    }//GEN-LAST:event_btnSendActionPerformed

    private void btnCloseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCloseActionPerformed

        btnClose.setEnabled(false);
        btnClose.setText("Closing...");

        try {

            session.exit();
            master.newSessionExit(session);

        } catch (IOException ex) {}

        btnClose.setText("Close");
        btnClose.setEnabled(true);

    }//GEN-LAST:event_btnCloseActionPerformed

    private void editorpaneMessageKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_editorpaneMessageKeyTyped

        // Enter typed
        if (evt.getKeyChar() == '\n') {

            // ENTER with CTRL --> Add the enter to the editor
            if (evt.getModifiers() == 2) {
                editorpaneMessage.setText(editorpaneMessage.getText() + '\n');
            }
            // Enter without CTRL --> Send the message.
            else {
                sendTypedMessage();
            }
        }
    }//GEN-LAST:event_editorpaneMessageKeyTyped


    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnClose;
    private javax.swing.JButton btnSend;
    private javax.swing.JEditorPane editorpaneMessage;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JLabel labelNickname;
    private javax.swing.JTextPane messages;
    // End of variables declaration//GEN-END:variables

    @Override
    public void newPrivateMessage(PrivateMessage message) {
        printNewMessage(message);
    }

    @Override
    public void newExitSessionMessage(SessionExitMessage event) {
        printExitMessage();
        isClosed = true;
    }

    /**
     * Send a typed message.
     */
    private void sendTypedMessage() {

        new SwingWorker<Object, Object>() {

            @Override
            protected Object doInBackground() {

                btnSend.setEnabled(false);
                btnSend.setText("Sending...");

                String message = editorpaneMessage.getText();
                if (message.length() != 0) {

                    try {
                        session.speak(message);
                    } catch (IOException ex) {
                        JOptionPane.showMessageDialog(
                                null, ex.getLocalizedMessage(),
                                "Exception", JOptionPane.WARNING_MESSAGE);
                    }
                }

                printMyMessage(message);
                editorpaneMessage.setText("");

                btnSend.setText("Send");
                btnSend.setEnabled(true);

                return null;
            }

        }.execute();
    }

    /**
     * Print to the messages my message.
     * @param message
     */
    private void printMyMessage(String message) {

        if (isClosed) {
            printClosedMessage();
            return;
        }

        StringBuilder builder = new StringBuilder(messages.getText());
        builder.append("\n");
        builder.append("Me :\n");
        builder.append(message);
        builder.append("\n");

        messages.setText(builder.toString());
    }

    /**
     * Print to the messages the new distant node message.
     * @param message
     */
    private void printNewMessage(PrivateMessage message) {

        StringBuilder builder = new StringBuilder(messages.getText());
        builder.append("\n");
        builder.append(session.getNode().getName());
        builder.append(" :\n");
        builder.append(message.getText());
        builder.append("\n");

        messages.setText(builder.toString());
    }

    /**
     * Print the distant node exit message.
     */
    private void printExitMessage() {

        StringBuilder builder = new StringBuilder(messages.getText());
        builder.append("\n");
        builder.append(session.getNode().getName());
        builder.append(" exit\n");
        builder.append("\n");
        
        messages.setText(builder.toString());
    }

    /**
     * Print a "error" message : session is closed
     */
    private void printClosedMessage() {

        StringBuilder builder = new StringBuilder(messages.getText());
        builder.append("\n");
        builder.append("This session is closed");
        builder.append("\n");

        messages.setText(builder.toString());
    }
}
